Code
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')Escribir un programa mediante el cual simular y visualizar la evolución del capital del jugador A
def apuesta(p:float):
if np.random.random() < p:
return 1
else:
return -1def juego(p:float, S:int, X0:int):
trayectoria = [X0]
X = X0
while (X > 0) and (X < S):
X += apuesta(p)
trayectoria.append(X)
return trayectoriap = 0.5
S = 10
X0 = 5
trayectoria = juego(p, S, X0)print('Trayectoria: ', trayectoria)Trayectoria: [5, 4, 3, 4, 3, 2, 1, 2, 1, 2, 3, 4, 3, 2, 3, 2, 1, 0]
plt.figure(figsize=(8,5))
plt.plot(trayectoria, marker='o')
plt.title('Juego de la ruina - Una trayectoria')
plt.ylim(-0.5, S+0.5)
plt.axhline(y=S, linestyle='--')
plt.axhline(y=0, linestyle='--')
plt.xlabel(r'Turno $n$')
plt.ylabel(r'Capital $X_n$')
plt.show()todas_trayectorias = []
for _ in range(5):
todas_trayectorias.append(juego(p, S, X0))plt.figure(figsize=(8,5))
for trayectoria in todas_trayectorias:
plt.plot(trayectoria, marker='o')
plt.title('Juego de la ruina - Varias trayectorias') # Added title for clarity
plt.ylim(-0.5, S+0.5)
plt.axhline(y=S, linestyle='--')
plt.axhline(y=0, linestyle='--')
plt.xlabel(r'Turno $n$')
plt.ylabel(r'Capital $X_n$')
plt.show()Desarrollar el programa anterior de manera de estimar, mediante la simulación de un número adecuado de trayectorias del capital del jugador A, la probabilidad de ruina.
def probabilidad_ruina(p:float, S:int, X0:int, N:int):
ruinas = 0
for _ in range(N):
trayectoria = juego(p, S, X0)
if trayectoria[-1] == 0:
ruinas += 1
return ruinas/Np = 0.7
S = 10
X0 = 5
N = 10000
print(f'Probabilidad de ruina: {probabilidad_ruina(p, S, X0, N)}')Probabilidad de ruina: 0.0141
fS = []
for X0 in range(S+1):
fS.append(probabilidad_ruina(p, S, X0, N))plt.figure(figsize=(8,5))
plt.plot(fS, marker='o')
plt.title('Probabilidad de ruina')
plt.xlabel(r'Capital inicial $X_0$')
plt.show()def probabilidad_ruina_Markov(p:float, S:int, X0:int, X1:int, N:int):
ruinas = 0
condicion = 0
for _ in range(N):
trayectoria = juego(p, S, X0)
if trayectoria[1] == X1:
condicion += 1
if trayectoria[-1] == 0:
ruinas += 1
return ruinas/condicionp = 0.5
S = 10
X0 = 5
N = 10000
p0 = probabilidad_ruina(p, S, X0+1, N)
p1 = probabilidad_ruina_Markov(p, S, X0, X0+1, N)
print(f'p0: {p0}\np1: {p1}')p0: 0.3962
p1: 0.39119222376512597
def simular_duracion_juego(p: float, S: int, X0: int) -> int:
trayectoria = [X0]
X = X0
turnos = 0
while (X > 0) and (X < S):
X += apuesta(p) ## funcion del ejercicio 1
turnos += 1
return turnosdef estimar_duracion_esperada(p: float, S: int, X0: int, N: int) -> float:
duraciones = []
for _ in range(N):
duraciones.append(simular_duracion_juego(p, S, X0))
return np.mean(duraciones)p_ej2_i = 0.5
S_ej2_i = 10
N_ej2_i = 5000
duracion_vs_X0 = []
for k_val in range(S_ej2_i + 1):
duracion_vs_X0.append(estimar_duracion_esperada(p_ej2_i, S_ej2_i, k_val, N_ej2_i))
print("Duración esperada vs. Capital inicial:", [float(d) for d in duracion_vs_X0])Duración esperada vs. Capital inicial: [0.0, 8.5572, 16.3292, 20.8324, 23.7448, 25.1652, 24.4272, 20.8436, 15.5248, 9.3192, 0.0]
plt.figure(figsize=(8,5))
plt.plot(range(S_ej2_i + 1), duracion_vs_X0, marker='o')
plt.title(f'Duración Esperada vs. Capital Inicial (S={S_ej2_i}, p={p_ej2_i})')
plt.xlabel(r'Capital inicial $X_0$')
plt.ylabel('Duración Esperada del Juego')
plt.xticks(range(S_ej2_i + 1))
plt.grid(True)
plt.show()X0_ej2_ii = 5
S_ej2_ii = 10
N_ej2_ii = 5000
probabilidades = np.linspace(0.1, 0.9, 9)
duracion_vs_p = []
for p_val in probabilidades:
duracion_vs_p.append(estimar_duracion_esperada(p_val, S_ej2_ii, X0_ej2_ii, N_ej2_ii))
print("Duración esperada vs. Probabilidad p:", [float(d) for d in duracion_vs_p])Duración esperada vs. Probabilidad p: [6.2168, 8.254, 12.3132, 19.2708, 25.3448, 19.6704, 12.3836, 8.302, 6.2856]
plt.figure(figsize=(8,5))
plt.plot(probabilidades, duracion_vs_p, marker='o')
plt.title(f'Duración Esperada vs. Probabilidad p (S={S_ej2_ii}, X0={X0_ej2_ii})')
plt.xlabel(r'Probabilidad $p$ de ganar')
plt.ylabel('Duración Esperada del Juego')
plt.grid(True)
plt.show()Visualizar las estimaciones de la duración esperada del juego y compararlas con las correspondientes expresiones analíticas.
def prob_ruina_analitica(p: float, S: int, k: int) -> float:
q = 1 - p
if p == 0.5:
return (S - k) / S
else:
ratio = q / p
return (ratio**k - ratio**S) / (1 - ratio**S)def duracion_esperada_analitica(p: float, S: int, k: int) -> float:
q = 1 - p
if p == 0.5:
return k * (S - k)
else:
prob_ganar_analitica = 1 - prob_ruina_analitica(p, S, k)
if p != q:
return (k / (q - p)) - (S / (q - p)) * ((1 - (q / p)**k) / (1 - (q / p)**S))
else:
return k * (S - k)duracion_analitica_X0 = []
for k_val in range(S_ej2_i + 1):
duracion_analitica_X0.append(duracion_esperada_analitica(p_ej2_i, S_ej2_i, k_val))
print("Duración analítica vs. Capital inicial:", [float(d) for d in duracion_analitica_X0])Duración analítica vs. Capital inicial: [0.0, 9.0, 16.0, 21.0, 24.0, 25.0, 24.0, 21.0, 16.0, 9.0, 0.0]
plt.figure(figsize=(10,6))
plt.plot(range(S_ej2_i + 1), duracion_vs_X0, marker='o', label='Simulado', linestyle='--')
plt.plot(range(S_ej2_i + 1), duracion_analitica_X0, marker='x', label='Analítico', linestyle='-')
plt.title(f'Comparación Duración Esperada vs. Capital Inicial (S={S_ej2_i}, p={p_ej2_i})')
plt.xlabel(r'Capital inicial $X_0$')
plt.ylabel('Duración Esperada del Juego')
plt.xticks(range(S_ej2_i + 1))
plt.grid(True)
plt.legend()
plt.show()duracion_analitica_p = []
for p_val in probabilidades:
duracion_analitica_p.append(duracion_esperada_analitica(p_val, S_ej2_ii, X0_ej2_ii))
print("Duración analítica vs. Probabilidad p:", [float(d) for d in duracion_analitica_p])Duración analítica vs. Probabilidad p: [6.249788314987299, 8.317073170731707, 12.14369501466276, 19.181818181818183, 25.0, 19.18181818181818, 12.143695014662754, 8.317073170731707, 6.249788314987299]
plt.figure(figsize=(10,6))
plt.plot(probabilidades, duracion_vs_p, marker='o', label='Simulado', linestyle='--')
plt.plot(probabilidades, duracion_analitica_p, marker='x', label='Analítico', linestyle='-')
plt.title(f'Comparación Duración Esperada vs. Probabilidad p (S={S_ej2_ii}, X0={X0_ej2_ii})')
plt.xlabel(r'Probabilidad $p$ de ganar')
plt.ylabel('Duración Esperada del Juego')
plt.grid(True)
plt.legend()
plt.show()Consideramos un juego de ruina del jugador con posibilidad de empate (también llamado lazy random walk): en el tiempo \(n\) la ganancia \(X_n\) del Jugador A puede aumentar en una unidad con probabilidad \(r \in (0; 1/2]\), disminuir en una unidad con probabilidad \(r\), o permanecer igual con probabilidad \(1 - 2r\). Definimos
\[ f (k) := P(RA | X_0 = k) \]
como la probabilidad de ruina del Jugador A, y
\[ h(k) := E[T_{0;S} | X_0 = k] \]
como la esperanza de la duración del juego \(T_{0;S}\) comenzando en \(X_0 = k\), para \(k = 0; 1; \dots ; S\).
Para encontrar la ecuación que satisface \(u_k\), la probabilidad de que el Jugador A se arruine comenzando con una fortuna k, utilizamos un análisis de primer paso. Consideramos el resultado del primer movimiento desde el estado k:
Por la ley de probabilidad total, podemos escribir: \(u_k = p \cdot u_{k+1} + q \cdot u_{k-1} + r \cdot u_k\)
Para simplificar, agrupamos los términos de \(u_k\): \(u_k (1-r) = p \cdot u_{k+1} + q \cdot u_{k-1}\)
Dado que \(p+q+r=1\), tenemos que \(1-r=p+q\). Sustituyendo: \((p+q)u_k = p \cdot u_{k+1} + q \cdot u_{k-1}\)
Reordenando obtenemos la ecuación en diferencias homogénea:
\(pu_{k+1} - (p+q)u_k + qu_{k-1} = 0, \text{para } 1 \leq k \leq N-1\) Las condiciones de contorno son los estados absorbentes:
\(u_0=1, u_N=0\)
Resolvemos la ecuación mediante su polinomio característico: \(p\lambda^2 - (p+q)\lambda + q = 0\)
Este polinomio se puede factorizar como \((p\lambda-q)(\lambda-1)=0\). Las raíces son: \(\lambda_1=1 \text{ y } \lambda_2 = \frac{q}{p}\).
Tenemos dos casos:
Caso 1: \(p \neq q\) Las raíces son distintas. La solución general es de la forma: \(u_k = A(\lambda_1)^k + B(\lambda_2)^k = A+B\left(\frac{q}{p}\right)^k\)
Aplicamos las condiciones de contorno:
\(u_0 = 1 \implies A+B=1\)
\(u_N = 0 \implies A+B\left(\frac{q}{p}\right)^N = 0\)
Resolviendo el sistema, obtenemos \(B = \frac{1}{1-(q/p)^N}\) y \(A = -B(q/p)^N\). La solución es:
\(u_k = \frac{(q/p)^k - (q/p)^N}{1-(q/p)^N}\)
Caso 2: \(p=q\) Las raíces son iguales (\(\lambda_1=\lambda_2=1\)). La solución general es: \(u_k = A(1)^k + Bk(1)^k = A+Bk\)
Aplicamos las condiciones de contorno:
\(u_0 = 1 \implies A=1\)
\(u_N = 0 \implies A+BN=0 \implies 1+BN=0 \implies B = -\frac{1}{N}\)
La solución es:
\(u_k = 1-\frac{k}{N} = \frac{N-k}{N}\)
Compatibilidad con la intuición: Sí, la solución es compatible. Notablemente, la probabilidad de ruina no depende de \(r\) (la probabilidad de empate). Un empate simplemente retrasa el juego, pero no altera el sesgo fundamental (\(p\) vs \(q\)) que determina el resultado final. La probabilidad de ruina es idéntica a la del juego de ruina del jugador estándar sin empates.
Nuevamente, usamos un análisis de primer paso para \(d_k\), la duración media del juego comenzando en \(k\). Cada paso toma 1 unidad de tiempo. \(d_k = 1 + p \cdot d_{k+1} + q \cdot d_{k-1} + r \cdot d_k\)
Agrupando los términos de \(d_k\) y usando \(1-r=p+q\): \((1-r)d_k = 1 + p \cdot d_{k+1} + q \cdot d_{k-1}\) \((p+q)d_k = 1 + p \cdot d_{k+1} + q \cdot d_{k-1}\)
Reordenando, obtenemos la ecuación en diferencias no homogénea:
\(pd_{k+1} - (p+q)d_k + qd_{k-1} = -1, \text{para } 1 \leq k \leq N-1\) Las condiciones de contorno son: Si el juego comienza en un estado absorbente, la duración es 0.
\(d_0=0, d_N=0\)
Buscamos una solución particular \(d_k^{(p)}\) para la ecuación no homogénea.
Caso 1: \(p \neq q\) Intentamos con una solución de la forma \(d_k^{(p)}=Ck\). \(pC(k+1)-(p+q)Ck+qC(k-1)=-1\) \(pCk+pC-pCk-qCk+qCk-qC=-1\) \(C(p-q)=-1 \implies C = \frac{1}{q-p}\)
Una solución particular es:
\(d_k^{(p)} = \frac{k}{q-p}\)
Caso 2: \(p=q\) El método anterior falla porque \(Ck\) es parte de la solución homogénea. Intentamos con \(d_k^{(p)} = Ck^2\). La ecuación es \(pd_{k+1}-2pd_k+pd_{k-1}=-1\). \(pC(k+1)^2 - 2pCk^2 + pC(k-1)^2 = -1\) \(pC(k^2+2k+1 - 2k^2 + k^2-2k+1) = -1\) \(pC(2)=-1 \implies C = -\frac{1}{2p}\)
Una solución particular es:
\(d_k^{(p)} = -\frac{k^2}{2p}\)
La solución general es la suma de la solución de la homogénea (\(d_k^{(h)}\)) y una particular (\(d_k^{(p)}\)).
Caso 1: \(p \neq q\) \(d_k = d_k^{(h)} + d_k^{(p)} = A+B\left(\frac{q}{p}\right)^k + \frac{k}{q-p}\)
Aplicamos las condiciones de contorno (\(d_0=0, d_N=0\)):
\(d_0=0 \implies A+B=0 \implies A=-B\)
\(d_N=0 \implies A+B\left(\frac{q}{p}\right)^N + \frac{N}{q-p} = 0\)
Sustituyendo \(A=-B\): \(B\left(\left(\frac{q}{p}\right)^N - 1\right) = -\frac{N}{q-p} \implies B = \frac{N}{(p-q)((q/p)^N-1)}\)
La solución completa es:
\(d_k = \frac{k}{q-p} + \frac{N}{(p-q)(1-(q/p)^N)}\left(\left(\frac{q}{p}\right)^k - 1\right)\)
Caso 2: \(p=q\) \(d_k = d_k^{(h)} + d_k^{(p)} = A+Bk-\frac{k^2}{2p}\)
Aplicamos las condiciones de contorno (\(d_0=0, d_N=0\)):
\(d_0=0 \implies A=0\)
\(d_N=0 \implies BN - \frac{N^2}{2p} = 0 \implies B = \frac{N}{2p}\)
La solución completa es:
\(d_k = \frac{Nk}{2p} - \frac{k^2}{2p} = \frac{k(N-k)}{2p}\)
Para el caso simétrico (\(p=q\)), la duración media es:
\(d_k = \frac{k(N-k)}{2p}\)
Recordando que \(p+q+r=1\) y \(p=q\), tenemos \(2p+r=1 \implies 2p=1-r\). La fórmula se puede reescribir como:
\(d_k = \frac{k(N-k)}{1-r}\)
Compatibilidad con la intuición: Sí, esta solución es muy intuitiva por dos razones principales:
Forma de la función: La función \(k(N-k)\) es una parábola invertida que es 0 en \(k=0\) y \(k=N\). Alcanza su máximo en \(k=N/2\). Esto significa que la duración esperada del juego es mayor cuando el jugador comienza a mitad de camino, lo más lejos posible de ambos estados absorbentes (ruina o victoria total).
Dependencia de \(r\): La duración media \(d_k\) es inversamente proporcional a \(1-r\). A medida que la probabilidad de empate \(r\) se acerca a 1, el denominador \(1-r\) se acerca a 0, y la duración media \(d_k \to \infty\). Esto tiene perfecto sentido: si los jugadores casi siempre empatan, el juego se “congela” en su estado actual y tardará una cantidad de tiempo extremadamente larga en llegar a su fin.